﻿using System;
using System.Threading;

namespace Sgr.Domain.Uow
{
    /// <summary>
    /// 默认工作单元跟踪器 - 负责通过AsyncLocal存储和跟踪当前工作单元
    /// </summary>
    public class DefaultUnitOfWorkTracker : IUnitOfWorkTracker
    {
        /// <summary>
        /// 使用 AsyncLocal 存储当前工作单元
        /// </summary>
        private readonly AsyncLocal<IUnitOfWork?> _currentUnitOfWork;

        /// <summary>
        /// 初始化 <see cref="DefaultUnitOfWorkTracker"/> 类的新实例
        /// </summary>
        public DefaultUnitOfWorkTracker()
        {
            _currentUnitOfWork = new AsyncLocal<IUnitOfWork?>();
        }

        /// <summary>
        /// 获取当前工作单元
        /// </summary>
        public IUnitOfWork? Current => _currentUnitOfWork.Value;

        /// <summary>
        /// 设置当前工作单元
        /// </summary>
        /// <param name="unitOfWork">工作单元实例</param>
        public void SetUnitOfWork(IUnitOfWork? unitOfWork)
        {
            _currentUnitOfWork.Value = unitOfWork;
        }

        /// <summary>
        /// 清理当前工作单元，通常在Dispose时调用
        /// </summary>
        /// <param name="unitOfWork">工作单元实例</param>
        public void ClearCurrent(IUnitOfWork unitOfWork)
        {
            // 只有当当前工作单元是传入的工作单元时才清理
            if (Current == unitOfWork)
            {
                // 恢复父工作单元
                _currentUnitOfWork.Value = unitOfWork.Outer;
            }
        }

        /// <summary>
        /// 检查并获取当前工作单元
        /// </summary>
        /// <returns>当前工作单元</returns>
        public IUnitOfWork? GetCurrentByChecking()
        {
            var uow = Current;

            // 跳过已释放或已完成的工作单元
            while (uow != null && (uow.IsDisposed || uow.IsCompleted))
            {
                uow = uow.Outer;
            }

            return uow;
        }
    }
}